From: David Vrabel Date: Thu, 22 Mar 2012 14:26:45 +0000 (+0000) Subject: device tree: add device_tree_for_each_node() X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=9cf4a9a467171c8a2c3d97c2bfadb1bc8b15a3d6;p=xen.git device tree: add device_tree_for_each_node() Add device_tree_for_each_node() to iterate over all nodes in a flat device tree. Use this in device_tree_early_init(). Signed-off-by: David Vrabel Committed-by: Ian Campbell --- diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c index 5329956279..8f5d8997da 100644 --- a/xen/common/device_tree.c +++ b/xen/common/device_tree.c @@ -68,7 +68,43 @@ static u32 __init prop_by_name_u32(const void *fdt, int node, return fdt32_to_cpu(*(uint32_t*)prop->data); } +#define MAX_DEPTH 16 + +/** + * device_tree_for_each_node - iterate over all device tree nodes + * @fdt: flat device tree. + * @func: function to call for each node. + * @data: data to pass to @func. + */ +int device_tree_for_each_node(const void *fdt, + device_tree_node_func func, void *data) +{ + int node; + int depth; + u32 address_cells[MAX_DEPTH]; + u32 size_cells[MAX_DEPTH]; + int ret; + + for ( node = 0, depth = 0; + node >=0 && depth >= 0; + node = fdt_next_node(fdt, node, &depth) ) + { + if ( depth >= MAX_DEPTH ) + continue; + + address_cells[depth] = prop_by_name_u32(fdt, node, "#address-cells"); + size_cells[depth] = prop_by_name_u32(fdt, node, "#size-cells"); + + ret = func(fdt, node, fdt_get_name(fdt, node, NULL), depth, + address_cells[depth-1], size_cells[depth-1], data); + if ( ret < 0 ) + return ret; + } + return 0; +} + static void __init process_memory_node(const void *fdt, int node, + const char *name, u32 address_cells, u32 size_cells) { const struct fdt_property *prop; @@ -81,15 +117,14 @@ static void __init process_memory_node(const void *fdt, int node, if ( address_cells < 1 || size_cells < 1 ) { early_printk("fdt: node `%s': invalid #address-cells or #size-cells", - fdt_get_name(fdt, node, NULL)); + name); return; } prop = fdt_get_property(fdt, node, "reg", NULL); if ( !prop ) { - early_printk("fdt: node `%s': missing `reg' property\n", - fdt_get_name(fdt, node, NULL)); + early_printk("fdt: node `%s': missing `reg' property\n", name); return; } @@ -106,30 +141,15 @@ static void __init process_memory_node(const void *fdt, int node, } } -#define MAX_DEPTH 16 - -static void __init early_scan(const void *fdt) +static int __init early_scan_node(const void *fdt, + int node, const char *name, int depth, + u32 address_cells, u32 size_cells, + void *data) { - int node; - int depth; - u32 address_cells[MAX_DEPTH]; - u32 size_cells[MAX_DEPTH]; - - for ( node = 0; depth >= 0; node = fdt_next_node(fdt, node, &depth) ) - { - if ( depth >= MAX_DEPTH ) - { - early_printk("fdt: node '%s': nested too deep\n", - fdt_get_name(fdt, node, NULL)); - continue; - } + if ( node_matches(fdt, node, "memory") ) + process_memory_node(fdt, node, name, address_cells, size_cells); - address_cells[depth] = prop_by_name_u32(fdt, node, "#address-cells"); - size_cells[depth] = prop_by_name_u32(fdt, node, "#size-cells"); - - if ( node_matches(fdt, node, "memory") ) - process_memory_node(fdt, node, address_cells[depth-1], size_cells[depth-1]); - } + return 0; } static void __init early_print_info(void) @@ -157,7 +177,7 @@ size_t __init device_tree_early_init(const void *fdt) if ( ret < 0 ) early_panic("No valid device tree\n"); - early_scan(fdt); + device_tree_for_each_node((void *)fdt, early_scan_node, NULL); early_print_info(); return fdt_totalsize(fdt); diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h index 28a3deef59..505f3e326e 100644 --- a/xen/include/xen/device_tree.h +++ b/xen/include/xen/device_tree.h @@ -28,10 +28,18 @@ struct dt_early_info { struct dt_mem_info mem; }; +typedef int (*device_tree_node_func)(const void *fdt, + int node, const char *name, int depth, + u32 address_cells, u32 size_cells, + void *data); + extern struct dt_early_info early_info; extern void *device_tree_flattened; size_t device_tree_early_init(const void *fdt); paddr_t device_tree_get_xen_paddr(void); +int device_tree_for_each_node(const void *fdt, + device_tree_node_func func, void *data); + #endif